package com.demo.common;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.springframework.util.StringUtils;

public abstract class ClassLoaderUtils {
	
	private static final String FOLDER_SEPARATOR = "/";
	private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
	
	public static ClassLoader getDefaultClassLoader() {
		ClassLoader cl = null;
		try {
			cl = Thread.currentThread().getContextClassLoader();
		}
		catch (Throwable ex) {
			// Cannot access thread context ClassLoader - falling back to system class loader...
		}
		if (cl == null) {
			// No thread context class loader -> use class loader of this class.
			cl = ClassLoaderUtils.class.getClassLoader();
		}
		return cl;
	}
	
    @SuppressWarnings("rawtypes")
	public static InputStream getResourceAsStream(String resourceName, Class callingClass) throws FileNotFoundException {
        URL url = getResource(ClassLoaderUtils.getRealPath(resourceName), callingClass);

        try {
            return (url != null) ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }
    

    /**
     * 加载资源
     * 使用参数类加载器、 默认类加载器、加载当前类的类加载器顺序加载
     * @param resourceName 资源
     * @param classLoader 类加载器
     * @return InputStream 资源
     */
    public static InputStream getResourceAsStream(String resourceName, ClassLoader classLoader) {
    	
    	//真实路径
    	String realResourceName = ClassLoaderUtils.getRealPath(resourceName);
    	URL url = null;
    	// 参数类加载器加载
    	if (classLoader != null) {
    		url = classLoader.getResource(resourceName);
    	}
    	// 默认类加载器加载
    	if (url == null) {
    		url = ClassLoaderUtils.getDefaultClassLoader().getResource(realResourceName);
    	}

    	// 当前类的类加载器加载
        if (url == null) {
            url = ClassLoaderUtils.class.getClassLoader().getResource(realResourceName);
        }

        try {
            return (url != null) ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }
    
    @SuppressWarnings("rawtypes")
	public static URL getResource(String resourceName, Class callingClass) throws FileNotFoundException {
    	//真实路径
    	//真实路径
    	String realResourceName = ClassLoaderUtils.getRealPath(resourceName);

    	ClassLoader classLoader = ClassLoaderUtils.getDefaultClassLoader();
    	
        URL url = classLoader.getResource(realResourceName);
        
        if (url != null) {
        	url = classLoader.getResource(realResourceName);
        }
        
        if (url == null) {
            url = ClassLoaderUtils.class.getClassLoader().getResource(realResourceName);
        }

        if (url == null) {
            ClassLoader cl = callingClass.getClassLoader();

            if (cl != null) {
                url = cl.getResource(realResourceName);
            }
        }
        if (url == null) {
        	try {
				File file = new File(realResourceName);
				if (file.exists()) {
					url = file.toURI().toURL();
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
        }
        if (url == null) {
        	throw new FileNotFoundException("file " + resourceName + " not found.");
        }

        return url;
    }
    
    @SuppressWarnings("rawtypes")
	public static String getResourcePath(String resourceName, Class callingClass) throws FileNotFoundException {
    	
    	URL url = getResource(resourceName, callingClass);
        return url.getPath();
    }
    
	public static String getResourcePath(String resourceName, ClassLoader classLoader) throws FileNotFoundException {
    	//真实路径
    	String realResourceName = ClassLoaderUtils.getRealPath(resourceName);

        URL url = classLoader.getResource(realResourceName);
        
        if (url != null) {
        	url = classLoader.getResource(realResourceName);
        }
        
        if (url == null) {
            url = ClassLoaderUtils.class.getClassLoader().getResource(realResourceName);
        }

        if (url == null) {
            ClassLoader cl = classLoader.getClass().getClassLoader();

            if (cl != null) {
                url = cl.getResource(realResourceName);
            }
        }
        if (url == null) {
        	try {
				File file = new File(realResourceName);
				if (file.exists()) {
					url = file.toURI().toURL();
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
        }
        if (url == null) {
        	throw new FileNotFoundException("file " + resourceName + " not found.");
        }
        return url.getPath();
    }
	
	public static String getRealPath(String configFile) {
		
		String pathToUse = configFile;
		if (configFile.startsWith("classpath:")) {
			configFile = configFile.substring("classpath:".length());
			pathToUse = StringUtils.replace(configFile, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);
		}
		if (pathToUse.startsWith("/")) {
			pathToUse = pathToUse.substring(1);
		}
		return pathToUse;
	}
	
    @SuppressWarnings("unchecked")
	public static <T> Class<T> loadClass(String className, Class<?> callingClass) throws ClassNotFoundException {
    	ClassLoader loader = ClassLoaderUtils.getDefaultClassLoader();
        try {
            return ((Class<T>) loader.loadClass(className));
        } catch (ClassNotFoundException e) {
            try {
                return (Class<T>) Class.forName(className);
            } catch (ClassNotFoundException ex) {
                    return (Class<T>) callingClass.getClassLoader().loadClass(className);
            }
        }
    }
}
